import Foundation
import UIKit
import Maaku

// MARK: - Font Style Implementation
public class MaakuFonts: Maaku.FontStyle {
    public var current: Maaku.Font = .systemFont(ofSize: 16)
    public var code: Maaku.Font = .monospacedSystemFont(ofSize: 14, weight: .regular)
    public var emphasis: Maaku.Font = .italicSystemFont(ofSize: 16)
    public var strong: Maaku.Font = .boldSystemFont(ofSize: 16)
    public var h1: Maaku.Font = .systemFont(ofSize: 28, weight: .bold)
    public var h2: Maaku.Font = .systemFont(ofSize: 24, weight: .bold)
    public var h3: Maaku.Font = .systemFont(ofSize: 20, weight: .semibold)
    public var h4: Maaku.Font = .systemFont(ofSize: 18, weight: .semibold)
    public var h5: Maaku.Font = .systemFont(ofSize: 16, weight: .medium)
    public var h6: Maaku.Font = .systemFont(ofSize: 15, weight: .medium)
    public var paragraphBlock: Maaku.Font = .systemFont(ofSize: 15, weight: .medium)
    
    // Required by Maaku.FontStyle
    public var blockQuote: Maaku.Font {
        return emphasis
    }
    
    public var codeBlock: Maaku.Font {
        return code
    }
    
    public var inlineCode: Maaku.Font {
        return code
    }
    
    public var link: Maaku.Font {
        return .systemFont(ofSize: 16, weight: .medium)
    }
    
    public var listItem: Maaku.Font {
        return current
    }

    public var paragraph: Maaku.Font = .systemFont(ofSize: 15, weight: .medium)
    
    public var strikethrough: Maaku.Font {
        return .systemFont(ofSize: 16, weight: .light)
    }
    
    public init() {}
}

// MARK: - Color Style Implementation
public class MaakuColors: Maaku.ColorStyle {
    public var text: Maaku.Color = .label
    public var background: Maaku.Color = .clear
    public var link: Maaku.Color = .systemBlue
    public var current: Maaku.Color = .label
    public var h1: Maaku.Color = .label
    public var h2: Maaku.Color = .label
    public var h3: Maaku.Color = .label
    public var h4: Maaku.Color = .label
    public var h5: Maaku.Color = .label
    public var h6: Maaku.Color = .label
    
    // Required by Maaku.ColorStyle
    public var inlineCodeForeground: Maaku.Color = .systemPink
    public var inlineCodeBackground: Maaku.Color = .secondarySystemBackground
    public var linkUnderline: Maaku.Color = .systemBlue
    public var paragraph: Maaku.Color = .label
    
    public var blockquoteBackground: Maaku.Color = .tertiarySystemBackground
    public var blockquoteBorder: Maaku.Color = .systemGray
    public var listItemPrefix: Maaku.Color = .secondaryLabel
    
    public init() {}
}

// MARK: - Style Implementation
public class MaakuStyle: Style {
    public var fonts: any Maaku.FontStyle
    public var colors: any Maaku.ColorStyle
    public var hasStrikethrough: Bool
    public var softbreakSeparator: String
    
    public var paragraphStyle: NSParagraphStyle = {
        let style = NSMutableParagraphStyle()
        style.paragraphSpacing = 12
        style.lineSpacing = 6
        style.headIndent = 0
        style.firstLineHeadIndent = 0
        style.tailIndent = 0
        return style
    }()
    
    public init(
        fonts: any Maaku.FontStyle = MaakuFonts(),
        colors: any Maaku.ColorStyle = MaakuColors(),
        hasStrikethrough: Bool = true,
        softbreakSeparator: String = "\n"
    ) {
        self.fonts = fonts
        self.colors = colors
        self.hasStrikethrough = hasStrikethrough
        self.softbreakSeparator = softbreakSeparator
    }
    
    // MARK: - Attribute Generators
    public var attributesForStyle: (any FontStyle, any ColorStyle) -> [NSAttributedString.Key: Any] = { fonts, colors in
        [
            .font: fonts.current,
            .foregroundColor: colors.current,
            .paragraphStyle: NSParagraphStyle.default
        ]
    }
    
    public var h1AttributesForStyle: (any FontStyle, any ColorStyle) -> [NSAttributedString.Key: Any] = { fonts, colors in
        let style = NSMutableParagraphStyle()
        style.paragraphSpacing = 16
        style.lineSpacing = 8
        return [
            .font: fonts.h1,
            .foregroundColor: colors.h1,
            .paragraphStyle: style
        ]
    }
    
    public var h2AttributesForStyle: (any FontStyle, any ColorStyle) -> [NSAttributedString.Key: Any] = { fonts, colors in
        let style = NSMutableParagraphStyle()
        style.paragraphSpacing = 14
        style.lineSpacing = 7
        return [
            .font: fonts.h2,
            .foregroundColor: colors.h2,
            .paragraphStyle: style
        ]
    }
    
    public var h3AttributesForStyle: (any FontStyle, any ColorStyle) -> [NSAttributedString.Key: Any] = { fonts, colors in
        let style = NSMutableParagraphStyle()
        style.paragraphSpacing = 12
        style.lineSpacing = 6
        return [
            .font: fonts.h3,
            .foregroundColor: colors.h3,
            .paragraphStyle: style
        ]
    }
    
    public var h4AttributesForStyle: (any FontStyle, any ColorStyle) -> [NSAttributedString.Key: Any] = { fonts, colors in
        [
            .font: fonts.h4,
            .foregroundColor: colors.h4,
            .paragraphStyle: NSParagraphStyle.default
        ]
    }
    
    public var h5AttributesForStyle: (any FontStyle, any ColorStyle) -> [NSAttributedString.Key: Any] = { fonts, colors in
        [
            .font: fonts.h5,
            .foregroundColor: colors.h5,
            .paragraphStyle: NSParagraphStyle.default
        ]
    }
    
    public var h6AttributesForStyle: (any FontStyle, any ColorStyle) -> [NSAttributedString.Key: Any] = { fonts, colors in
        [
            .font: fonts.h6,
            .foregroundColor: colors.h6,
            .paragraphStyle: NSParagraphStyle.default
        ]
    }
    
    public var blockQuoteAttributesForStyle: (any FontStyle, any ColorStyle) -> [NSAttributedString.Key: Any] = { fonts, colors in
        let style = NSMutableParagraphStyle()
        style.paragraphSpacing = 12
        style.lineSpacing = 6
        style.headIndent = 20
        style.firstLineHeadIndent = 20
        return [
            .font: fonts.blockQuote,
            .foregroundColor: colors.blockQuote,
            .backgroundColor: colors.blockquoteBackground,
            .paragraphStyle: style
        ]
    }
    
    public var codeBlockAttributesForStyle: (any FontStyle, any ColorStyle) -> [NSAttributedString.Key: Any] = { fonts, colors in
        let style = NSMutableParagraphStyle()
        style.paragraphSpacing = 12
        style.lineSpacing = 4
        return [
            .font: fonts.codeBlock,
            .foregroundColor: colors.current,
            .backgroundColor: colors.inlineCodeBackground,
            .paragraphStyle: style
        ]
    }
    
    public var inlineCodeAttributesForStyle: (any FontStyle, any ColorStyle) -> [NSAttributedString.Key: Any] = { fonts, colors in
        [
            .font: fonts.inlineCode,
            .foregroundColor: colors.inlineCodeForeground,
            .backgroundColor: colors.inlineCodeBackground,
            .paragraphStyle: NSParagraphStyle.default
        ]
    }
    
    public var linkAttributesForStyle: (any FontStyle, any ColorStyle) -> [NSAttributedString.Key: Any] = { fonts, colors in
        [
            .font: fonts.link,
            .foregroundColor: colors.link,
            .underlineColor: colors.linkUnderline,
            .underlineStyle: NSUnderlineStyle.single.rawValue,
            .paragraphStyle: NSParagraphStyle.default
        ]
    }
    
    public var listItemAttributesForStyle: (any FontStyle, any ColorStyle) -> [NSAttributedString.Key: Any] = { fonts, colors in
        let style = NSMutableParagraphStyle()
        style.paragraphSpacing = 8
        style.lineSpacing = 4
        style.headIndent = 20
        style.firstLineHeadIndent = 0
        return [
            .font: fonts.listItem,
            .foregroundColor: colors.current,
            .paragraphStyle: style
        ]
    }
    
    public var paragraphAttributesForStyle: (any FontStyle, any ColorStyle) -> [NSAttributedString.Key: Any] = { fonts, colors in
        [
            .font: fonts.paragraph,
            .foregroundColor: colors.paragraph,
            .paragraphStyle: NSParagraphStyle.default
        ]
    }
    
    public var emphasisAttributesForStyle: (any FontStyle, any ColorStyle) -> [NSAttributedString.Key: Any] = { fonts, colors in
        [
            .font: fonts.emphasis,
            .foregroundColor: colors.current,
            .paragraphStyle: NSParagraphStyle.default
        ]
    }
    
    public var strongAttributesForStyle: (any FontStyle, any ColorStyle) -> [NSAttributedString.Key: Any] = { fonts, colors in
        [
            .font: fonts.strong,
            .foregroundColor: colors.current,
            .paragraphStyle: NSParagraphStyle.default
        ]
    }
    
    public var strikethroughAttributesForStyle: (any FontStyle, any ColorStyle) -> [NSAttributedString.Key: Any] = { fonts, colors in
        [
            .font: fonts.strikethrough,
            .foregroundColor: colors.current,
            .strikethroughStyle: NSUnderlineStyle.single.rawValue,
            .paragraphStyle: NSParagraphStyle.default
        ]
    }
}
